/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cuatroenraya.jugadores;

import cuatroenraya.util.Estruc;
import cuatroenraya.util.HeuristicaList;
import java.util.ArrayList;

/**
 *
 * @author Hernan
 */
public class heuristica {

    private Node nodo;
    private ArrayList<Posicion> posiciones = new ArrayList<Posicion>();
    private ArrayList<Posicion> posicionesAux = new ArrayList<Posicion>();
    private ArrayList<Posicion> posicionesOponente = new ArrayList<Posicion>();
    //Array con la cantidad de fichas por filas
    private int[] cantFichasFilas = new int[8];
    //Array con la cantidad de fichas por filas
    private int[] cantFichasColum = new int[8];
    private boolean flagDefensa = false;

    public heuristica() {
    }

    public void heuristica1(Node nodo, HeuristicaList heuList, ArrayList<Posicion> misFichas, ArrayList<Posicion> fichasOponente) {
        int diff = 0;
        int diffMenor = -1;
        int columFinalNodo = 0;
        int filaFinalNodo = nodo.getJugada().getPosicionFinal().getY();
        posiciones = misFichas;
        posicionesOponente = fichasOponente;
        //posicionesAux.clear();//Limpia arreglo auxiliar
        eliminarNodoMov(nodo.getJugada().getPosicionInicial());//Arma lista aux de fichas limpiando la que analizo y las -1
        countFichas();//determina la cantidad de fichas por fila, sumando un valor extra si son continuas
        for (Posicion pos : posicionesAux) {
            diff += Math.abs(filaFinalNodo - pos.getY());
            diff += Math.abs(columFinalNodo - pos.getX());
            if (diff < diffMenor || diffMenor == -1) {
                diffMenor = diff;
            }
        }

        nodo.Puntuacion = (int) (diffMenor == 0 ? 0 : 30 / Math.abs(diffMenor)); //20  
//        nodo.Puntuacion = (int) 20 / Math.abs(diffMenor);
        defensa(nodo, filaFinalNodo, columFinalNodo);
        nodo.Puntuacion += evitarBloqueo(filaFinalNodo, columFinalNodo);
        nodo.Puntuacion += (cantFichasFilas[nodo.getJugada().getPosicionFinal().getY()]) * 3;//3
        nodo.Puntuacion += (cantFichasColum[nodo.getJugada().getPosicionFinal().getX()]) * 3;//3

        nodo.Puntuacion += countDiagonales(nodo);
        String msj = "puntuacion= " + nodo.Puntuacion + " Fila:" + filaFinalNodo + " Colum: " + columFinalNodo;
        //System.out.println("puntuacion= "+ nodo.Puntuacion +" Fila:"+nodo.getJugada().getPosicionFinal().getY()+" Colum: "+nodo.getJugada().getPosicionFinal().getX());
        Estruc est = new Estruc(nodo.Puntuacion, msj);
        heuList.list.add(est);
    }

    public int evitarBloqueo(int filaFinal, int columFinal) {
        int resta = 0;
        int restaAux = 0;
        for (Posicion opo : posicionesOponente) {
            if (!flagDefensa) {
                if (filaFinal == opo.getY()) {//estan en la misma fila
                    restaAux = Math.abs(columFinal - opo.getX());
                    if (restaAux < resta) {
                        resta = restaAux;
                    }
                } else {
                    if (columFinal == opo.getX()) {//estan en la misma fila
                        restaAux = Math.abs(filaFinal - opo.getY());
                        if (restaAux < resta) {
                            resta = restaAux;
                        }
                    }
                }
            } else {
                resta = 0;
            }
        }
        if (!flagDefensa) {
            if (resta == 1) {
                return -30;//penaliza ficha del oponente al lado
            } else {
                return 0;
            }
        } else {
            flagDefensa = false;
            return 200;
        }
    }

    //Asigna pesos a las filas y columnas en las cuales el oponente tiene fichas continuas.
    public void defensa(Node nodo, int filaFinalNodo, int columFinalNodo) {
        int resta = 0;
        int continuos = 0;
        for (Posicion p : posicionesOponente) {
            //cantFichasFilas[p.getY()]++;
            //cantFichasColum[p.getX()]++;
            for (Posicion pp : posicionesOponente) {
                if (p.getY() != pp.getY() || p.getX() != pp.getX()) {//Controla que no se compare una ficha con ella misma
                    if (p.getY() == pp.getY() && pp.getY() == filaFinalNodo) {//Se calcula distancia de columnas de fichas existentes que estan en la misma fila
                        resta = (p.getX() - pp.getX());
                        if (resta == 1) {
                            if ((pp.getX() + 2 < 8) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY()][pp.getX() + 2]) {
                                continuos = 3;
                            } else {
                                //continuos = 2;
                                if ((pp.getX() - 1 > -1) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY()][pp.getX() - 1]) {
                                    continuos = 3;
                                }

                            }
                            if (continuos == 3) {//20
                                //cantFichasFilas[p.getY()] += 50;//Se le asigna mas peso a la fila porque hay fichas continuas
                                flagDefensa = true;
                            }
                            //continuos = 0;
                        } else {
                            if (resta == -1) {
                                if ((pp.getX() + 1 < 8) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY()][pp.getX() + 1]) {
                                    continuos = 3;
                                } else {
                                    //continuos = 2;
                                    if ((pp.getX() - 2 > -1) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY()][pp.getX() - 2]) {
                                        continuos = 3;
                                    }

                                }
                                if (continuos == 3) {//20
                                    //cantFichasFilas[p.getY()] += 50;//Se le asigna mas peso a la fila porque hay fichas continuas
                                    flagDefensa = true;
                                }
                                //continuos = 0;
                            }
                        }

                    }
                }
                if (p.getX() == pp.getX() && pp.getX() == columFinalNodo) {//Se calcula distancia de filas de fichas existentes que estan en la misma columna
                    resta = (p.getY() - pp.getY());
                    if (resta == 1) {
                        if ((pp.getY() + 2 < 8) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY() + 2][pp.getX()]) {
                            continuos = 3;
                        } else {
                            //continuos = 2;
                            if (( pp.getY() - 1 > -1) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY() - 1][pp.getX()]) {
                                continuos = 3;
                            }
                        }
                        if (continuos == 3) {//20
                            //cantFichasColum[p.getX()] += 50;//Se le asigna mas peso a la Columna porque hay fichas continuas                                
                            flagDefensa = true;
                        }
                        //continuos = 0;
                    }else{
                        if (resta == -1) {
                        if ((pp.getY() - 2 > -1) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY() - 2][pp.getX()]) {
                            continuos = 3;
                        } else {
                            //continuos = 2;
                            if (( pp.getY() + 1 < 8) && nodo.getTablero()[p.getY()][p.getX()] == nodo.getTablero()[pp.getY() + 1][pp.getX()]) {
                                continuos = 3;
                            }
                        }
                        if (continuos == 3) {//20
                            //cantFichasColum[p.getX()] += 50;//Se le asigna mas peso a la Columna porque hay fichas continuas                                
                            flagDefensa = true;
                        }
                        //continuos = 0;
                    }
                    }
                }
            }
        }

    }

    // Devuelve un peso calculando la cantidad de elementos en todas las diagonales
    public int countDiagonales(Node nodo) { //Contador de las 4 diagonales desde un punto Posicion
        int peso = 0;
        int row = 0;
        int col = 0;

        //Caso diagonal descendente derecha
        int cte = 30;//10
        /*for(int i=nodo.getJugada().getPosicionFinal().getY()+1; i<8;i++){ 
        for(int j=nodo.getJugada().getPosicionFinal().getX()+1; j<8;j++){
        if(nodo.getTablero()[i][j]==nodo.getFichaJugador()){
        peso+=cte;
        }
        cte--;//Resta la cte sumada la peso a medida que se aleja por la diagonal
        }            
        }*/
        row = nodo.getJugada().getPosicionFinal().getY() + 1;
        col = nodo.getJugada().getPosicionFinal().getX() + 1;
        while (row < 8 && col < 8) {
            if (nodo.getTablero()[row][col] == nodo.getFichaJugador()) {
                peso += cte;
            }
            cte=cte-1;//Resta la cte sumada la peso a medida que se aleja por la diagonal
            row++;
            col++;
        }

        //Caso diagonal ascendente izquierda
        cte = 30;
        /*for(int i=nodo.getJugada().getPosicionFinal().getY()-1; i>=0;i--){ 
        for(int j=nodo.getJugada().getPosicionFinal().getX()-1; j>=0;j--){
        if(nodo.getTablero()[i][j]==nodo.getFichaJugador()){
        peso+=cte;
        }
        cte--;//Resta la cte sumada la peso a medida que se aleja por la diagonal
        }            
        }*/
        row = nodo.getJugada().getPosicionFinal().getY() - 1;
        col = nodo.getJugada().getPosicionFinal().getX() - 1;
        while (row > 0 && col > 0) {
            if (nodo.getTablero()[row][col] == nodo.getFichaJugador()) {
                peso += cte;
            }
            cte=cte-1;//Resta la cte sumada la peso a medida que se aleja por la diagonal
            row--;
            col--;
        }

        //Caso diagonal descendente izquierda
        cte = 30;
        /*for(int i=nodo.getJugada().getPosicionFinal().getY()+1; i<8;i++){ 
        for(int j=nodo.getJugada().getPosicionFinal().getX()-1; j>=0;j--){
        if(nodo.getTablero()[i][j]==nodo.getFichaJugador()){
        peso+=cte;
        }
        cte--;//Resta la cte sumada la peso a medida que se aleja por la diagonal
        }            
        }*/
        row = nodo.getJugada().getPosicionFinal().getY() + 1;
        col = nodo.getJugada().getPosicionFinal().getX() - 1;
        while (row < 8 && col > 0) {
            if (nodo.getTablero()[row][col] == nodo.getFichaJugador()) {
                peso += cte;
            }
            cte=cte-1;//Resta la cte sumada la peso a medida que se aleja por la diagonal
            row++;
            col--;
        }

        //Caso diagonal ascendente derecha
        cte = 30;
        /*for(int i=nodo.getJugada().getPosicionFinal().getY()-1; i>=0;i--){ 
        for(int j=nodo.getJugada().getPosicionFinal().getX()+1; j<8;j++){
        if(nodo.getTablero()[i][j]==nodo.getFichaJugador()){
        peso+=cte;
        }
        cte--;//Resta la cte sumada la peso a medida que se aleja por la diagonal
        }            
        }*/
        row = nodo.getJugada().getPosicionFinal().getY() - 1;
        col = nodo.getJugada().getPosicionFinal().getX() + 1;
        while (row > 0 && col < 8) {
            if (nodo.getTablero()[row][col] == nodo.getFichaJugador()) {
                peso += cte;
            }
            cte=cte-1;//Resta la cte sumada la peso a medida que se aleja por la diagonal
            row--;
            col++;
        }

        return peso;//devuelve el valor de peso calculado para todas las diagonales
    }

    // Cuenta la cantidad de fichas por filas y columnas
    public void countFichas() {
        int resta = 0;
        for (Posicion p : posicionesAux) {
            cantFichasFilas[p.getY()]++;
            cantFichasColum[p.getX()]++;
            for (Posicion pp : posicionesAux) {
                if (p.getY() != pp.getY() || p.getX() != pp.getX()) {//Controla que no se compare una ficha con ella misma
                    if (p.getY() == pp.getY()) {//Se calcula distancia de columnas de fichas existentes que estan en la misma fila
                        resta = Math.abs(p.getX() - pp.getX());
                        switch (resta) {
                            case 1:
                                cantFichasFilas[p.getY()] += 30;//Se le asigna mas peso a la fila porque hay fichas continuas
                                break;
                            case 2:
                                cantFichasFilas[p.getY()] += 20;//Se le asigna mas peso a la fila porque hay fichas continuas
                                break;
                            case 3:
                                cantFichasFilas[p.getY()] += 10;//Se le asigna mas peso a la fila porque hay fichas continuas
                                break;
                        }
                    }
                    if (p.getX() == pp.getX()) {//Se calcula distancia de filas de fichas existentes que estan en la misma columna
                        resta = Math.abs(p.getY() - pp.getY());
                        switch (resta) {
                            case 1:
                                cantFichasColum[p.getX()] += 30;//Se le asigna mas peso a la Columna porque hay fichas continuas
                                break;
                            case 2:
                                cantFichasColum[p.getX()] += 20;//Se le asigna mas peso a la Columna porque hay fichas continuas
                                break;
                            case 3:
                                cantFichasColum[p.getX()] += 10;//Se le asigna mas peso a la Columna porque hay fichas continuas
                                break;
                        }
                    }
                }
            }
        }
    }

    //Elimina de la lista de fichas la ficha que queremos evaluar para la heuristica
    public void eliminarNodoMov(Posicion pos) {
        //posicionesAux.clear();
        for (Posicion p : posiciones) {
            if ((p.getY() != pos.getY() && p.getX() != pos.getX()) || (p.getY() != -1 && p.getX() != -1)) {
                posicionesAux.add(p);
            }
        }
    }
}
